use core::sync::atomic::{AtomicI64, AtomicPtr, AtomicUsize, Ordering};

pub unsafe fn mi_atomic_add(p: *mut i64, add: i64) -> i64 {
    AtomicI64::from_ptr(p).fetch_add(add, Ordering::Relaxed)
}

pub unsafe fn mi_atomic_subtract(p: *mut usize, sub: usize) -> usize {
    AtomicUsize::from_ptr(p).fetch_sub(sub, Ordering::Relaxed)
}

pub fn mi_atomic_compare_exchange_ptr(p: *mut usize, newp: usize, compare: usize) -> bool {
    unsafe {
        let p = AtomicPtr::from_ptr(p as *mut *mut ());
        let newp = newp as *mut ();
        let compare = compare as *mut ();
        p.compare_exchange(compare, newp, Ordering::Relaxed, Ordering::SeqCst)
            .is_ok()
    }
}

pub unsafe fn mi_atomic_yield() {
    core::arch::asm!("pause");
}

pub unsafe fn mi_atomic_increment(p: *mut usize) -> usize {
    AtomicUsize::from_ptr(p).fetch_add(1, Ordering::Relaxed)
}

pub unsafe fn mi_atomic_decrement(p: *mut usize) -> usize {
    AtomicUsize::from_ptr(p).fetch_sub(1, Ordering::Relaxed)
}
